import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.vp.*;
import javax.swing.JFrame;



/**
* Darstellung einer Kugel mit unterschiedlicher Tesselierung
*
* @author Frank Klawonn
* Letzte Aenderung 01.07.2005
*/
public class TesselationResolution extends JFrame
{

  //Der Canvas, auf den gezeichnet wird.
  public Canvas3D myCanvas3D;


  public TesselationResolution()
  {
    //Mechanismus zum Schliessen des Fensters und beenden des Programms
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    //Standardeinstellung fuer das Betrachteruniversum
    myCanvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());


    //Aufbau des SimpleUniverse:
    //Zuerst Erzeugen zusammen mit dem Canvas
    SimpleUniverse simpUniv = new SimpleUniverse(myCanvas3D);


    //Standardpositionierung des Betrachters
    simpUniv.getViewingPlatform().setNominalViewingTransform();


    //Die Szene wird in dieser Methode erzeugt.
    createSceneGraph(simpUniv);


    //Hinzufuegen von Licht
    addLight(simpUniv);


    //Hierdurch kann man mit der Maus den Betrachterstandpunkt veraendern
    OrbitBehavior ob = new OrbitBehavior(myCanvas3D);
    ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE));
    simpUniv.getViewingPlatform().setViewPlatformBehavior(ob);


    //Darstellung des Canvas/Fensters:
    setTitle("Kugel, dargestellt mit verschiedener Aufloesung");
    setSize(700,700);
    getContentPane().add("Center", myCanvas3D);
    setVisible(true);

  }




  public static void main(String[] args)
  {
     TesselationResolution tr = new TesselationResolution();
  }





  //In dieser Methode werden die Objekte der Szene aufgebaut und dem
  //SimpleUniverse su hinzugefuegt.
  public void createSceneGraph(SimpleUniverse su)
  {

    // Create the root of the branch graph
    BranchGroup theScene = new BranchGroup();


    //Erzeuge eine Appearance fuer die Kugel
    Color3f ambientColourSphere = new Color3f(0.2f,0.2f,0.2f);
    Color3f emissiveColourSphere = new Color3f(0.0f,0.0f,0.0f);
    Color3f diffuseColourSphere = new Color3f(0.6f,0.6f,0.6f);
    Color3f specularColourSphere = new Color3f(0.5f,0.5f,0.5f);

    float shininessSphere = 20.0f;

    Appearance sphereApp = new Appearance();

    sphereApp.setMaterial(new Material(ambientColourSphere,emissiveColourSphere,
                           diffuseColourSphere,specularColourSphere,shininessSphere));


    //Es sollen n Kugeln mit Radius r dargestellt werden.
    int n = 5;
    float r = 0.15f;
    float shift = 2*r+0.05f;

    //Arrays fuer die Kugeln, deren Transformationen und Transformationsgruppen
    //zur Positionierung.
    Sphere[] spheres = new Sphere[n];
    TransformGroup[] tg = new TransformGroup[n];
    Transform3D[] tf = new Transform3D[n];

    //Erzeuge die Kugeln, ihre zugehoerigen Transformationen
    //und Transformationsgruppen, fuege sie zur Szene hinzu.
    for (int i=0; i<n; i++)
    {
      spheres[i] = new Sphere(r,Sphere.GENERATE_NORMALS,4+i*i*i,sphereApp);
      tf[i] = new Transform3D();
      tf[i].setTranslation(new Vector3f(-0.95f+r+shift*i,0.0f,0.0f));
      tg[i] = new TransformGroup(tf[i]);
      tg[i].addChild(spheres[i]);
      theScene.addChild(tg[i]);
    }


    //Erzeuge einen weissen Hintergrund
    Background bg = new Background(new Color3f(1.0f,1.0f,1.0f));
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),1000.0);
    bg.setApplicationBounds(bounds);
    theScene.addChild(bg);



    theScene.compile();

    //Hinzufuegen der Szene
    su.addBranchGraph(theScene);

  }





  //Hier wird etwas Licht zu der Szene hinzugefuegt.
  public void addLight(SimpleUniverse su)
  {

    BranchGroup bgLight = new BranchGroup();

    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);


    //parallel einfallende Lichtstrahlen
    Color3f lightColour = new Color3f(1.0f, 1.0f, 1.0f);
    Vector3f lightDir  = new Vector3f(1.0f, -1.0f, -1.0f);
    DirectionalLight light = new DirectionalLight(lightColour, lightDir);
    light.setInfluencingBounds(bounds);
    bgLight.addChild(light);



    //Streulicht
    Color3f ambientLightColour = new Color3f(0.5f, 0.5f, 0.5f);
    AmbientLight ambLight = new AmbientLight(ambientLightColour);
    ambLight.setInfluencingBounds(bounds);
    bgLight.addChild(ambLight);


    su.addBranchGraph(bgLight);
  }



}
